package net.guerlab.smart.wx.api.autoconfig;

import lombok.AllArgsConstructor;
import me.chanjar.weixin.common.error.WxErrorException;
import net.guerlab.commons.exception.ApplicationException;
import net.guerlab.smart.wx.api.WxMaApi;
import net.guerlab.smart.wx.core.domain.LoginResponse;
import net.guerlab.smart.wx.core.domain.MaEncryptedData;
import net.guerlab.smart.wx.service.service.WxMaLoginService;
import net.guerlab.smart.wx.service.service.WxMaManagerService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.*;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.lang.NonNull;

/**
 * @author guer
 */
@Configuration
@Conditional(WxMaApiLocalServiceAutoConfigure.WrapperCondition.class)
public class WxMaApiLocalServiceAutoConfigure {

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    @Bean
    @ConditionalOnBean(WxMaLoginService.class)
    public WxMaApi wxMaApiLocalServiceWrapper(WxMaLoginService service, WxMaManagerService managerService) {
        return new WxMaApiLocalServiceWrapper(service, managerService);
    }

    @SuppressWarnings("WeakerAccess")
    static class WrapperCondition implements Condition {

        @Override
        public boolean matches(@NonNull ConditionContext context, @NonNull AnnotatedTypeMetadata metadata) {
            try {
                ClassLoader classLoader = WxMpApiLocalServiceAutoConfigure.WrapperCondition.class.getClassLoader();
                return classLoader.loadClass("net.guerlab.smart.wx.service.service.WxMaLoginService") != null
                        && classLoader.loadClass("net.guerlab.smart.wx.service.service.WxMaManagerService") != null;
            } catch (Exception e) {
                return false;
            }
        }
    }

    @AllArgsConstructor
    private static class WxMaApiLocalServiceWrapper implements WxMaApi {

        private final WxMaLoginService service;

        private final WxMaManagerService managerService;

        @Override
        public LoginResponse login(String appId, String code) {
            try {
                return service.login(appId, code, "inside", "inside");
            } catch (Exception e) {
                throw new ApplicationException(e.getLocalizedMessage(), e);
            }
        }

        @Override
        public LoginResponse register(String appId, String openId, MaEncryptedData encryptedData) {
            try {
                return service.register(appId, openId, encryptedData);
            } catch (Exception e) {
                throw new ApplicationException(e.getLocalizedMessage(), e);
            }
        }

        @Override
        public String getAccessToken(String appId) {
            try {
                return managerService.getService(appId).getAccessToken();
            } catch (WxErrorException e) {
                throw new ApplicationException(e.getError().getErrorMsg(), e.getError().getErrorCode());
            }
        }
    }

}
